<?php
namespace app\home\controller;
use think\facde\Db;
use think\Log;
use pay\wechat\WxPay;
use pay\ali\AliPay;

class Notify {

    public function receive(){

        require_once("./alipay/alipay.config.php");
        require_once("./alipay/lib/alipay_notify.class.php");
        file_put_contents(RUNTIME_PATH.'/log.txt',serialize($_REQUEST), FILE_APPEND);
        $pay = M('plugin')->where(['code'=>'alipayMobile','type'=>'payment'])->field('config_value')->find();
        $config = unserialize($pay['config_value']);

        $alipay_config['partner']		= $config['alipay_partner'];
        $alipay_config['key']			= $config['alipay_key'];

        $alipay_config['seller_id']	= $alipay_config['partner'];
        $alipayNotify = new \AlipayNotify($alipay_config);
        $verify_result = $alipayNotify->verifyNotify();

        if($verify_result) {file_put_contents(RUNTIME_PATH.'/log.txt','\n\n verify ok', FILE_APPEND);
            $out_trade_no = $_REQUEST['out_trade_no'];
            //支付宝交易号
            $trade_no = $_REQUEST['trade_no'];
            //交易状态
            $trade_status = $_REQUEST['trade_status'];

            if($trade_status == 'TRADE_FINISHED'){

            }else if ($trade_status == 'TRADE_SUCCESS') {file_put_contents(RUNTIME_PATH.'/log.txt','\n\n TRADE_SUCCESS', FILE_APPEND);
                Db::startTrans();
                $rs = $this->getCal($out_trade_no,$trade_no);file_put_contents(RUNTIME_PATH.'/log.txt','\n\n '.serialize($rs), FILE_APPEND);
                if(!$rs['status']){
                    Db::rollback();
                    echo 'fail';exit();
                }else{
                    Db::commit();
                    echo 'success';exit;
                }
            }
        }else {
            echo "fail";
        }

    }

    //微信回调
    //回调
    public function noticeys(){
        file_put_contents(RUNTIME_PATH.'/log.txt','\n\n wx start', FILE_APPEND);
        vendor('Weixinpay.Weixin');
        $payClass = new \Weixin(array(),'');
        $payInfo = $payClass->notice();

        if($payInfo['err_code'] === 0){ file_put_contents(RUNTIME_PATH.'/log.txt','\n\n wx no error', FILE_APPEND);
            //逻辑
            if($payInfo['order_param']['trade_no']){

                $out_trade_no=$payInfo['order_param']['trade_no'];
                $third_id=$payInfo['order_param']['third_id'];
                file_put_contents(RUNTIME_PATH.'/log.txt','\n\n wx '.($out_trade_no)."---".$third_id, FILE_APPEND);
                Db::startTrans();
                $rs = $this->getCal($out_trade_no,$third_id,1);
                if(!$rs['status']){
                    file_put_contents(RUNTIME_PATH.'/log.txt','\n\n wx cal error '.($rs['msg']), FILE_APPEND);
                    Db::rollback();
                    exit('fail');
                }else{
                    file_put_contents(RUNTIME_PATH.'/log.txt','\n\n wx cal success ', FILE_APPEND);
                    Db::commit();
                    exit('success');
                }
            }
        }else{

            file_put_contents(RUNTIME_PATH.'/log.txt','\n\n  wx error '.serialize($payInfo), FILE_APPEND);
            exit('fail');
        }

    }

    //微信回调
    public function notify_wx(){
        $params = file_get_contents('php://input');
        $headers = request()->header();
        writeLog('微信回调进入','notify');
        writeLog('回调head数据'.json_encode($headers),'notify');
        writeLog('回调body数据'.json_encode($params),'notify');
        $paysdk = new WxPay();
        $response = $paysdk->notify_wx($headers,$params);
        writeLog('回调验证'.json_encode($response),'notify');
        if(!empty($response['trade_state']) && $response['trade_state'] === 'SUCCESS'){
            //逻辑
            $trader_no = $response['out_trade_no'];
            if($trader_no){
                $out_trade_no = $trader_no;
                $third_id = $response['transaction_id'];
                Db::startTrans();
                $rs = $this->getCal($out_trade_no,$third_id,1);
                if(!$rs['status']){
                    writeLog('商城逻辑处理'.$rs['msg'],'notify');
                    file_put_contents(RUNTIME_PATH.'/log.txt','\n\n wx cal error '.($rs['msg']), FILE_APPEND);
                    Db::rollback();
                    exit('fail');
                }else{
                    writeLog('处理成功'.$rs['msg'],'notify');
                    Db::commit();
                    exit('success');
                }
            }
        }else{
            exit('fail');
        }

    }
    //微信退款回调
    public function notify_wx_refund(){
        $params = file_get_contents('php://input');
        $headers = request()->header();
        writeLog('微信退款回调进入','notify_refund');
        writeLog('回调head数据'.json_encode($headers),'notify_refund');
        writeLog('回调body数据'.json_encode($params),'notify_refund');
        $paysdk = new WxPay();
        $response = $paysdk->notify_wx($headers,$params);
        writeLog('回调验证'.json_encode($response),'notify_refund');
        if(!empty($response['trade_state']) && $response['trade_state'] === 'SUCCESS'){
            //逻辑
            $trader_no = $response['out_trade_no'];
            if($trader_no){
                $out_trade_no = $trader_no;
                $third_id = $response['transaction_id'];
                Db::startTrans();

                    Db::commit();

            }
        }else{
            exit('fail');
        }

    }
    //支付宝回调
    public function notify_ali(){
        $params = input('post.');
        writeLog('支付宝回调进入','notify');
        writeLog('回调数据'.json_encode($params),'notify');
        $paysdk = new Alipay();
        $params['fund_bill_list'] = htmlspecialchars_decode(htmlspecialchars_decode($params['fund_bill_list']));
        $verify = $paysdk->notify_ali($params);
//        dump($verify);exit;
        writeLog('回调验证'.$verify,'notify');
        if($verify){
            //逻辑
            $out_trade_no = $params['out_trade_no'];
            $trader_no = $params['trade_no'];
            if($out_trade_no){
                writeLog($out_trade_no."---".$trader_no,'notify');
                Db::startTrans();
                $rs = $this->getCal($out_trade_no,$trader_no,1);
                if(!$rs['status']){
                    writeLog('商城逻辑处理'.$rs['msg'],'notify');
                    Db::rollback();
                    exit('fail');
                }else{
                    writeLog('处理成功'.$rs['msg'],'notify');
                    Db::commit();
                    exit('success');
                }
            }
        }else{
            exit('fail');
        }

    }

    public function pay($subject,$out_trade_no,$total_amount){
        $input = new \WxPayUnifiedOrder();
        $input->SetBody($subject);
        $input->SetOut_trade_no($out_trade_no);
        $input->SetTotal_fee($total_amount * 100);
        $input->SetNotify_url("回调地址");
        $input->SetTrade_type("MWEB");
        $scene_info = '{"h5_info":{"type":"Wap","wap_url":"域名","wap_name":"企业名称"}}';
        $input->SetValues("scene_info",$scene_info);

        $wxOrder = \WxPayApi::unifiedOrder($input);
        if ($wxOrder['return_code'] != 'SUCCESS' ||
            $wxOrder['result_code'] != 'SUCCESS'
        )
        {
            Log::record($wxOrder, 'error');
            Log::record('获取预支付订单失败', 'error');
        }
        return $wxOrder;
    }
    protected function getCal($out_trade_no,$trade_no,$zfb=1){
        $map = ['order_no' => $out_trade_no,'status'=>0];
        $info = Db::name('payment')->where($map)->find();
        if($info){
            //先更新在线支付
            $rs = Db::name('payment')->where(['id'=>$info['id']])->save(['status'=>1,'pay_time'=>time(),'trade_no'=>$trade_no]);
            if(!$rs){
                return ['status'=>0,'msg'=>'更新在线支付状态失败'];
            }
            writeLog('支付成功','notify');
            $table = $info['table'];

            if($table=='order'){
                $model = model($table);
                $pk =$model->getPk();

                //钱包
                $payment = $info['payment'];
                if($payment){
                    $payment = unserialize($payment);
                }
                writeLog('处理订单','notify');

                //订单的有可能是多个总订单一起支付
                $ids = explode(",",$info['ids']);
                foreach($ids as $pid){
                    //更新订单状态
                    $save = ['order_status'=>1,'pay_time'=>time(),'pay_code'=>$trade_no];

                    //如果有钱包支付
                    if($payment[$pid]){
                        $save['payment'] = serialize($payment[$pid]);
                    }
                    $rs = Db::name($table)->where([$pk=>$pid])->update($save);
                    if(!$rs){
                        writeLog('更新支付表状态失败','notify');
                        return ['status'=>0,'msg'=>'更新支付表状态失败'];
                    }else{
                        //支付后
                        if(method_exists($model,'afterPay')) {
                            $res = $model->afterPay($pid);
                            if ($res['status'] != 1) {
                                writeLog('afterPay处理失败'.$res['msg'],'notify');
                                return ['status'=>0,'msg'=>'更新支付表后续操作失败'.$res['msg']];
                            }
                        }

                        //钱包扣款
                        if($payment[$pid]){
                            foreach($payment[$pid] as $wk=>$money){
                                if($wk!='onlinepay' && $money>=0.01){
                                    $rs = qianbao($info['user_id'],-$money,$wk,$info['payname'],'支付单号'.$pid);
                                    if(!$rs['status']){
                                        writeLog('扣除其他钱包余额失败'.$rs['msg'],'notify');
                                        return ['status'=>0,'msg'=>'扣除其他钱包余额失败'.$rs['msg']];
                                    }
                                }

                            }
                        }
                    }
                }
            }elseif($table=='recharge_log'){
                Db::name('recharge_log')->whereIn('id',$info['ids'])->update(['order_status'=>1,'pay_time'=>time(),'trade_no'=>$trade_no]);

                $rs = qianbao($info['user_id'],$info['pay_price'],'money',$info['payname'],'充值单号'.$trade_no);
                if(!$rs['status']){
                    return ['status'=>0,'msg'=>'充值钱包余额失败'.$rs['msg']];
                }
            }
            writeLog($out_trade_no.'处理完成','notify');
        }else{
            return ['status'=>0,'msg'=>'未找到相关支付表信息'];
        }

        return ['status'=>1];
    }
}